package org.japo.java.matisse.samples;

import java.awt.Color;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import org.japo.java.entities.Matricula;
import org.japo.java.entities.Nif;

/**
 *
 * @author José A. Pacheco Ondoño - joanpaon@gmail.com
 */
public class MatriculaValidada extends javax.swing.JFrame {

    // Referencia al modelo
    private Matricula modelo;

    // Fichero de persistencia
    private final String FICHERO = "matricula.txt";

    // Semáforos de validación
    private boolean expedienteOK;
    private boolean nombreOK;
    private boolean apellidosOK;
    private boolean nifOK;

    // Expresiones regulares de validación
    private final String ER_EXPEDIENTE = "[0-9]{1,5}";
    private final String ER_NOMBRE = ".{3,50}";
    private final String ER_APELLIDOS = ".{3,50}";
//    private final String ER_NIF = "[0-9]{8}[A-Z]";

    public MatriculaValidada() {
        iniciarAnterior();
        initComponents();
        iniciarPosterior();
    }

    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        btgCurso = new javax.swing.ButtonGroup();
        btgTurno = new javax.swing.ButtonGroup();
        pnlIdentificacion = new javax.swing.JPanel();
        lblExpediente = new javax.swing.JLabel();
        txfExpediente = new javax.swing.JTextField();
        lblNombre = new javax.swing.JLabel();
        txfNombre = new javax.swing.JTextField();
        lblApellidos = new javax.swing.JLabel();
        txfApellidos = new javax.swing.JTextField();
        lblNif = new javax.swing.JLabel();
        txfNif = new javax.swing.JTextField();
        pnlMatricula = new javax.swing.JPanel();
        lblCiclo = new javax.swing.JLabel();
        cbbCiclo = new javax.swing.JComboBox();
        lblCurso = new javax.swing.JLabel();
        rbtCurso1 = new javax.swing.JRadioButton();
        rbtCurso2 = new javax.swing.JRadioButton();
        rbtCurso3 = new javax.swing.JRadioButton();
        lblTurno = new javax.swing.JLabel();
        rbtTurnoM = new javax.swing.JRadioButton();
        rbtTurnoV = new javax.swing.JRadioButton();
        rbtTurnoN = new javax.swing.JRadioButton();
        rbtTurnoD = new javax.swing.JRadioButton();
        lblRepetidor = new javax.swing.JLabel();
        cbxRepetidor = new javax.swing.JCheckBox();
        pnlAlmacenamiento = new javax.swing.JPanel();
        btnCargar = new javax.swing.JButton();
        btnGuardar = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Matriculación");
        setResizable(false);

        pnlIdentificacion.setBorder(javax.swing.BorderFactory.createTitledBorder("Identificación"));

        lblExpediente.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        lblExpediente.setText("Expediente");

        txfExpediente.setText("0");
        txfExpediente.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                txfExpedienteFocusGained(evt);
            }
            public void focusLost(java.awt.event.FocusEvent evt) {
                txfExpedienteFocusLost(evt);
            }
        });

        lblNombre.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        lblNombre.setText("Nombre");

        txfNombre.setText("Nombre");
        txfNombre.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                txfNombreFocusGained(evt);
            }
            public void focusLost(java.awt.event.FocusEvent evt) {
                txfNombreFocusLost(evt);
            }
        });

        lblApellidos.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        lblApellidos.setText("Apellidos");

        txfApellidos.setText("Apellidos");
        txfApellidos.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                txfApellidosFocusGained(evt);
            }
            public void focusLost(java.awt.event.FocusEvent evt) {
                txfApellidosFocusLost(evt);
            }
        });

        lblNif.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        lblNif.setText("NIF");

        txfNif.setText("0000000T");
        txfNif.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                txfNifFocusGained(evt);
            }
            public void focusLost(java.awt.event.FocusEvent evt) {
                txfNifFocusLost(evt);
            }
        });

        javax.swing.GroupLayout pnlIdentificacionLayout = new javax.swing.GroupLayout(pnlIdentificacion);
        pnlIdentificacion.setLayout(pnlIdentificacionLayout);
        pnlIdentificacionLayout.setHorizontalGroup(
            pnlIdentificacionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlIdentificacionLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(pnlIdentificacionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(lblNif, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(lblApellidos, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(lblNombre, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(lblExpediente, javax.swing.GroupLayout.Alignment.TRAILING))
                .addGap(18, 18, 18)
                .addGroup(pnlIdentificacionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(txfNombre)
                    .addComponent(txfExpediente, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(txfApellidos)
                    .addComponent(txfNif, javax.swing.GroupLayout.DEFAULT_SIZE, 146, Short.MAX_VALUE))
                .addContainerGap())
        );

        pnlIdentificacionLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {lblApellidos, lblExpediente, lblNif, lblNombre});

        pnlIdentificacionLayout.setVerticalGroup(
            pnlIdentificacionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlIdentificacionLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(pnlIdentificacionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lblExpediente)
                    .addComponent(txfExpediente, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(pnlIdentificacionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lblNombre)
                    .addComponent(txfNombre, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(pnlIdentificacionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lblApellidos)
                    .addComponent(txfApellidos, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(pnlIdentificacionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lblNif)
                    .addComponent(txfNif, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pnlIdentificacionLayout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {lblApellidos, lblExpediente, lblNif, lblNombre, txfApellidos, txfExpediente, txfNif, txfNombre});

        pnlMatricula.setBorder(javax.swing.BorderFactory.createTitledBorder("Matrícula"));

        lblCiclo.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        lblCiclo.setText("Ciclo");

        cbbCiclo.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "ASI", "ASIR", "DAI", "DAM", "DAW", "ESI", "SMR", " " }));
        cbbCiclo.setSelectedIndex(4);

        lblCurso.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        lblCurso.setText("Curso");

        btgCurso.add(rbtCurso1);
        rbtCurso1.setSelected(true);
        rbtCurso1.setText("1");

        btgCurso.add(rbtCurso2);
        rbtCurso2.setText("2");

        btgCurso.add(rbtCurso3);
        rbtCurso3.setText("3");

        lblTurno.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        lblTurno.setText("Turno");

        btgTurno.add(rbtTurnoM);
        rbtTurnoM.setSelected(true);
        rbtTurnoM.setText("M");

        btgTurno.add(rbtTurnoV);
        rbtTurnoV.setText("V");

        btgTurno.add(rbtTurnoN);
        rbtTurnoN.setText("N");

        btgTurno.add(rbtTurnoD);
        rbtTurnoD.setText("D");

        lblRepetidor.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
        lblRepetidor.setText("Repetidor");

        javax.swing.GroupLayout pnlMatriculaLayout = new javax.swing.GroupLayout(pnlMatricula);
        pnlMatricula.setLayout(pnlMatriculaLayout);
        pnlMatriculaLayout.setHorizontalGroup(
            pnlMatriculaLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlMatriculaLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(pnlMatriculaLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(pnlMatriculaLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                        .addComponent(lblCurso, javax.swing.GroupLayout.DEFAULT_SIZE, 57, Short.MAX_VALUE)
                        .addComponent(lblCiclo, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addComponent(lblTurno, javax.swing.GroupLayout.PREFERRED_SIZE, 57, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(lblRepetidor, javax.swing.GroupLayout.PREFERRED_SIZE, 47, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(pnlMatriculaLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(cbxRepetidor)
                    .addGroup(pnlMatriculaLayout.createSequentialGroup()
                        .addComponent(rbtTurnoM)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(rbtTurnoV)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(rbtTurnoN)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(rbtTurnoD))
                    .addGroup(pnlMatriculaLayout.createSequentialGroup()
                        .addComponent(rbtCurso1)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(rbtCurso2)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(rbtCurso3))
                    .addComponent(cbbCiclo, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap(35, Short.MAX_VALUE))
        );

        pnlMatriculaLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {lblCiclo, lblCurso, lblRepetidor, lblTurno});

        pnlMatriculaLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {cbxRepetidor, rbtCurso1, rbtCurso2, rbtCurso3, rbtTurnoD, rbtTurnoM, rbtTurnoN, rbtTurnoV});

        pnlMatriculaLayout.setVerticalGroup(
            pnlMatriculaLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlMatriculaLayout.createSequentialGroup()
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .addGroup(pnlMatriculaLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lblCiclo)
                    .addComponent(cbbCiclo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(pnlMatriculaLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lblCurso)
                    .addComponent(rbtCurso1)
                    .addComponent(rbtCurso2)
                    .addComponent(rbtCurso3))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(pnlMatriculaLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(lblTurno)
                    .addComponent(rbtTurnoM)
                    .addComponent(rbtTurnoV)
                    .addComponent(rbtTurnoN)
                    .addComponent(rbtTurnoD))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(pnlMatriculaLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(lblRepetidor)
                    .addComponent(cbxRepetidor))
                .addGap(17, 17, 17))
        );

        pnlMatriculaLayout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {cbxRepetidor, lblCiclo, lblCurso, lblRepetidor, lblTurno, rbtCurso1, rbtCurso2, rbtCurso3, rbtTurnoD, rbtTurnoM, rbtTurnoN, rbtTurnoV});

        pnlAlmacenamiento.setBorder(javax.swing.BorderFactory.createTitledBorder("Almacenamiento"));

        btnCargar.setText("Cargar");
        btnCargar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnCargarActionPerformed(evt);
            }
        });

        btnGuardar.setText("Guardar");
        btnGuardar.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnGuardarActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout pnlAlmacenamientoLayout = new javax.swing.GroupLayout(pnlAlmacenamiento);
        pnlAlmacenamiento.setLayout(pnlAlmacenamientoLayout);
        pnlAlmacenamientoLayout.setHorizontalGroup(
            pnlAlmacenamientoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlAlmacenamientoLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(btnCargar, javax.swing.GroupLayout.PREFERRED_SIZE, 78, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 52, Short.MAX_VALUE)
                .addComponent(btnGuardar, javax.swing.GroupLayout.PREFERRED_SIZE, 83, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap())
        );

        pnlAlmacenamientoLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {btnCargar, btnGuardar});

        pnlAlmacenamientoLayout.setVerticalGroup(
            pnlAlmacenamientoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(pnlAlmacenamientoLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(pnlAlmacenamientoLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(btnCargar)
                    .addComponent(btnGuardar))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(pnlIdentificacion, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(pnlMatricula, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(pnlAlmacenamiento, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {pnlAlmacenamiento, pnlIdentificacion, pnlMatricula});

        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(pnlIdentificacion, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(pnlMatricula, javax.swing.GroupLayout.PREFERRED_SIZE, 150, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(pnlAlmacenamiento, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        pack();
        setLocationRelativeTo(null);
    }// </editor-fold>//GEN-END:initComponents

    private void btnGuardarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnGuardarActionPerformed
        procesarGuardar();
    }//GEN-LAST:event_btnGuardarActionPerformed

    private void btnCargarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnCargarActionPerformed
        procesarCargar();
    }//GEN-LAST:event_btnCargarActionPerformed

    private void txfExpedienteFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txfExpedienteFocusGained
        txfExpediente.setForeground(Color.BLACK);
        txfExpediente.setBackground(Color.CYAN);
    }//GEN-LAST:event_txfExpedienteFocusGained

    private void txfNombreFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txfNombreFocusGained
        txfNombre.setForeground(Color.BLACK);
        txfNombre.setBackground(Color.CYAN);
    }//GEN-LAST:event_txfNombreFocusGained

    private void txfApellidosFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txfApellidosFocusGained
        txfApellidos.setForeground(Color.BLACK);
        txfApellidos.setBackground(Color.CYAN);
    }//GEN-LAST:event_txfApellidosFocusGained

    private void txfNifFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txfNifFocusGained
        txfNif.setForeground(Color.BLACK);
        txfNif.setBackground(Color.CYAN);
    }//GEN-LAST:event_txfNifFocusGained

    private void txfExpedienteFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txfExpedienteFocusLost
        txfExpediente.setBackground(Color.WHITE);
        expedienteOK = validarCampoTexto(txfExpediente, ER_EXPEDIENTE, "*");
    }//GEN-LAST:event_txfExpedienteFocusLost

    private void txfNombreFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txfNombreFocusLost
        txfNombre.setBackground(Color.WHITE);
        nombreOK = validarCampoTexto(txfNombre, ER_NOMBRE, "*");
    }//GEN-LAST:event_txfNombreFocusLost

    private void txfApellidosFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txfApellidosFocusLost
        txfApellidos.setBackground(Color.WHITE);
        apellidosOK = validarCampoTexto(txfApellidos, ER_APELLIDOS, "*");
    }//GEN-LAST:event_txfApellidosFocusLost

    private void txfNifFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_txfNifFocusLost
        txfNif.setBackground(Color.WHITE);
        nifOK = validarCampoNif(txfNif);
    }//GEN-LAST:event_txfNifFocusLost

    public static void main(String args[]) {
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Windows".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(MatriculaValidada.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(MatriculaValidada.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(MatriculaValidada.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(MatriculaValidada.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>
        //</editor-fold>

        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new MatriculaValidada().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.ButtonGroup btgCurso;
    private javax.swing.ButtonGroup btgTurno;
    private javax.swing.JButton btnCargar;
    private javax.swing.JButton btnGuardar;
    private javax.swing.JComboBox cbbCiclo;
    private javax.swing.JCheckBox cbxRepetidor;
    private javax.swing.JLabel lblApellidos;
    private javax.swing.JLabel lblCiclo;
    private javax.swing.JLabel lblCurso;
    private javax.swing.JLabel lblExpediente;
    private javax.swing.JLabel lblNif;
    private javax.swing.JLabel lblNombre;
    private javax.swing.JLabel lblRepetidor;
    private javax.swing.JLabel lblTurno;
    private javax.swing.JPanel pnlAlmacenamiento;
    private javax.swing.JPanel pnlIdentificacion;
    private javax.swing.JPanel pnlMatricula;
    private javax.swing.JRadioButton rbtCurso1;
    private javax.swing.JRadioButton rbtCurso2;
    private javax.swing.JRadioButton rbtCurso3;
    private javax.swing.JRadioButton rbtTurnoD;
    private javax.swing.JRadioButton rbtTurnoM;
    private javax.swing.JRadioButton rbtTurnoN;
    private javax.swing.JRadioButton rbtTurnoV;
    private javax.swing.JTextField txfApellidos;
    private javax.swing.JTextField txfExpediente;
    private javax.swing.JTextField txfNif;
    private javax.swing.JTextField txfNombre;
    // End of variables declaration//GEN-END:variables

    // Control + Aspecto > Modelo
    private void actualizarModelo() {
        // Expediente
        modelo.setExpediente(txfExpediente.getText());

        // Nombre
        modelo.setNombre(txfNombre.getText());

        // Apellidos
        modelo.setApellidos(txfApellidos.getText());

        // Nif
        modelo.setNif(Nif.convertirNif(txfNif.getText()));

        // Ciclo
        modelo.setCiclo((String) cbbCiclo.getSelectedItem());

        // Curso
        char curso = '0';
        if (rbtCurso1.isSelected()) {
            curso = '1';
        } else if (rbtCurso2.isSelected()) {
            curso = '2';
        } else if (rbtCurso3.isSelected()) {
            curso = '3';
        }
        modelo.setCurso(curso);

        // Turno
        char turno = '0';
        if (rbtTurnoM.isSelected()) {
            turno = 'M';
        } else if (rbtTurnoV.isSelected()) {
            turno = 'V';
        } else if (rbtTurnoN.isSelected()) {
            turno = 'N';
        } else if (rbtTurnoD.isSelected()) {
            turno = 'D';
        }
        modelo.setTurno(turno);

        // Repetidor
        modelo.setRepetidor(cbxRepetidor.isSelected());
    }

    private void exportarModelo() throws Exception {
        // Proceso de exportación
        try (PrintWriter salida = new PrintWriter(
                new FileWriter(FICHERO))) {

            // Expediente
            String linea = modelo.getExpediente() + ",";

            // Nombre
            linea += modelo.getNombre() + ",";

            // Apellidos
            linea += modelo.getApellidos() + ",";

            // Nif
            linea += modelo.getNif().toString() + ",";

            // Ciclo
            linea += modelo.getCiclo() + ",";

            // Curso
            linea += modelo.getCurso() + ",";

            // Turno
            linea += modelo.getTurno() + ",";

            // Repetidor
            linea += modelo.isRepetidor();

            // Escribe la linea de texto
            salida.println(linea);
        }
    }

    // Persistencia > Modelo
    private void importarModelo() throws Exception {
        try (BufferedReader entrada = new BufferedReader(
                new FileReader(FICHERO))) {

            // Lee los datos de la matricula actual
            String linea = entrada.readLine();

            // Procesa la linea actual
            StringTokenizer st = new StringTokenizer(linea, ",");

            // Expediente
            modelo.setExpediente(st.nextToken());

            // Nombre
            modelo.setNombre(st.nextToken());

            // Apellidos
            modelo.setApellidos(st.nextToken());

            // Nif
            modelo.setNif(Nif.convertirNif(st.nextToken()));

            // Ciclo
            modelo.setCiclo(st.nextToken());

            // Curso
            modelo.setCurso(st.nextToken().charAt(0));

            // Turno
            modelo.setTurno(st.nextToken().charAt(0));

            // Repetidor
            modelo.setRepetidor(Boolean.parseBoolean(st.nextToken()));
        }
    }

    // Modelo > Controles
    private void actualizarControl() {
        // Expediente
        txfExpediente.setText(modelo.getExpediente());

        // Nombre
        txfNombre.setText(modelo.getNombre());

        // Apellidos
        txfApellidos.setText(modelo.getApellidos());

        // Nif
        txfNif.setText(modelo.getNif().toString());

        // Ciclo
        cbbCiclo.setSelectedItem(modelo.getCiclo());

        // Curso
        switch (modelo.getCurso()) {
            case '1':
                rbtCurso1.doClick();
                break;
            case '2':
                rbtCurso2.doClick();
                break;
            case '3':
                rbtCurso3.doClick();
        }

        // Turno
        switch (modelo.getTurno()) {
            case 'M':
                rbtTurnoM.doClick();
                break;
            case 'V':
                rbtTurnoV.doClick();
                break;
            case 'N':
                rbtTurnoN.doClick();
                break;
            case 'D':
                rbtTurnoD.doClick();
        }

        // Repetidor
        cbxRepetidor.setSelected(modelo.isRepetidor());
    }

    private void iniciarAnterior() {
    }

    private void iniciarPosterior() {
        // Diseño interfaz > Modelo
        generarModelo();
        
        // Comprobar validez campos
        comprobarValidez();
    }

    // Diseño interfaz > Nuevo modelo
    private void generarModelo() {
        // Modelo por defecto
        modelo = new Matricula();

        // Control (Tiempo de diseño) > Modelo
        actualizarModelo();
    }

    // Aplicación > Persistencia 
    private void procesarGuardar() {
        if (comprobarValidez()) {
            try {
                // Control + Aspecto > Modelo
                actualizarModelo();

                // Modelo > Persistencia
                exportarModelo();
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(this, "Error al guardar los datos.");
            }
        } else {
            JOptionPane.showMessageDialog(this, "Hay datos erróneos.");
        }
    }

    // Persistencia > Aplicación
    private void procesarCargar() {
        try {
            // Persistencia > Modelo
            importarModelo();

            // Modelo > Controles
            actualizarControl();
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, "Error al cargar los datos");
        }
    }

    // Campo de texto + ExpReg + Texto campo vacío
    private boolean validarCampoTexto(JTextField txfActual,
            String expReg, String textoCampoVacio) {
        // Semáforo de validación
        boolean validacionOK = false;

        try {
            // Texto del campo - No espaciadores
            String textoActual = txfActual.getText().trim();

            // Comprueba campo vacío
            if (textoActual.equals("")) {
                textoActual = textoCampoVacio;
            }

            // Restaura el texto formateado
            txfActual.setText(textoActual);

            // Patrón de la expresión regular
            Pattern patron = Pattern.compile(expReg);

            // Aplica el patrón al texto de prueba
            Matcher detector = patron.matcher(textoActual);

            // Comprueba la coincidencia
            if (detector.matches()) {
                // Contenido correcto
                txfActual.setForeground(Color.BLACK);

                // Actualiza el semáforo
                validacionOK = true;
            } else {
                // Marca error
                txfActual.setForeground(Color.RED);
            }
        } catch (PatternSyntaxException pse) {
            // Marca error
            txfActual.setForeground(Color.RED);

            // ExpReg errónea - Depurar
            JOptionPane.showMessageDialog(this,
                    "Expresión regular errónea");
        }

        // Resultado de la validación
        return validacionOK;
    }

    private boolean validarCampoNif(JTextField txfActual) {
        // Semáforo de validación
        boolean validacionOK;

        // Texto del campo - No espaciadores
        String textoActual = txfActual.getText().trim();

        // Comprueba campo vacío
        if (textoActual.equals("")) {
            textoActual = new Nif().toString();
        }
        
        // Actualiza el texto del campo
        txfActual.setText(textoActual);
        
        // Valida el dato
        validacionOK = Nif.validarNif(textoActual);

        // Colorea el campo
        if (validacionOK) {
            txfNif.setForeground(Color.BLACK);
        } else {
            txfNif.setForeground(Color.RED);
        }

        // Resultado validación
        return validacionOK;
    }

    private boolean comprobarValidez() {
        // Validar todos los campos
        expedienteOK = validarCampoTexto(txfExpediente, ER_EXPEDIENTE, "*");
        nombreOK = validarCampoTexto(txfNombre, ER_NOMBRE, "*");
        apellidosOK = validarCampoTexto(txfApellidos, ER_APELLIDOS, "*");
        nifOK = validarCampoNif(txfNif);

        // Comprobar semáforos
        return expedienteOK && nombreOK && apellidosOK && nifOK;
    }
}
